home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Design
/
WB Collection.iso
/
workbench werkzeuge
/
kickstart tools
/
softboot3.31
/
softboot.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-04-07
|
34KB
|
976 lines
/*
SoftBoot V3.31 for any A3000/68030 or 68040 system; Tested OK
if run in startup-sequence on an A4000.
by Greg Tibbs 10/25/1992 ; some code from SetCPU V1.4 by Dave Haynie
MAIN PROGRAM
Assumptions: The 040 for the A3000 only works under 2.0+, so there are
assumptions that exec knows about an 040, that ROMsize
is 512K. ZorroIII space is automatically found and MMU
tables allocated and initialized. ZorroII caching
defaults to on unless explicitly turned off or a
BridgeBoard is found in the system. Compiled using
SAS/C V6.00. Assembly module SofTag.asm must be
linked in. The Assembly module has the magic to
perform reboot recovery as well as talk to the 030
and 040 MMUs directly.
*/
#define PROGRAM_VERSION "V3.31"
#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <libraries/configvars.h>
#include <proto/all.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include "proto.h"
#define ROUND030 0x00008000L
#define ROUND 0x00002000L
#define ROMSIZE 0x00080000L
#define BONUSSIZE1_3 0x00045000L
#define FASTROMLOC 0x07f80000L
#define BASEROMLOC 0x00f80000L
#define TABSIZE (128L * sizeof(ULONG))
#define LEV3TABSIZE 0x2000L
#define Z3STARTADDR 0x10000000L
#define Z3ENDADDR 0xffffffffL
#define WALL 0x100L
#define WALLSIZE 2*WALL
#define PFLUSHA040 0xf518
#define CINVA040 0xf4d8
#define MOVEC 0x4e7b
#define NOP 0x4e71
#define TCMASK030 0x80000000L
#define FASTROMADDRMASK 0x7000000L
#define MMU030TABLESIZE 0x8000L
#define Z3L3SIZEPERBLOCK 0x4000L
#define Z3L2SIZEPERBLOCK 0X200L
#define PAGESIZE030 0X80000L
#define PDTRESIDENT 0x01L
#define UDTRESIDENT 0x03L
#define CM_GLOBAL 0x400L
#define WR_PROTECT 0x04L
#define CM_COPYBACK 0x020L
#define CM_INH_SER 0x040L
#define CM_INH_NONSER 0x060L
#define L1MASK ~0x1ffL /* Masks used in MMU table addresses for Level 1, 2 & 3 tables */
#define L2MASK ~0x7fL
#define L3MASK ~0x1fffL
int CXBRK(void) {return(0L);}
/* External Variables */
extern struct ExecBase *SysBase;
/* Communication to the assembly module is via common
memory areas, rather than passing the data on the stack or via
a register. */
__far extern ULONG PhyRomStart, LogRomStart, SRP, CRP0;
__far extern ULONG CRP1, TC030;
__far extern ULONG StartRom, BusErr, CatchRom, Z3cache;
__far extern ULONG TC, MemListArray[24], NumMemAreas;
__far extern ULONG GetTC030(void), GetTC040(void), GetCPUType(void);
__far extern void MyColdReboot(void), JTRom(void), SpeedRom(void), MakeRomTag(void);
__far extern void JTRom13030(void), MakeRomTag13(void), ForceTTX(void);
__far extern void KillRomTags(void), SF_Supervisor(void), CachesOff(void);
struct ConfigureIt
{
ULONG StartAddr;
ULONG EndAddr;
ULONG BridgeBoard;
};
/* WallFreemem must be used to return all WALLed memory allocations */
void WallFreeMem( void *Address, ULONG size)
{
Address=(void *)((ULONG)Address-WALL);
size += WALLSIZE;
FreeMem(Address,size);
}
/* KillRomTags() is an assembly function to overwrite the ID so leftover
copies of the romtags embedded in this executable won't accidentially get
found and run on reboot. Fastrom in particular was dangerous as if
the romtag was found in RAM which was loaded during the fastrom operation,
the MMU might get setup with a working MMU environment which would get
stomped on as soon as any program overwrites that area as the MMU memory
areas would not be autoallocated and protected. The Ram occupied by the
romtag would not be protected either, BTW.
A Real RomTag is only made when it is intended to softload a new
operating system. Currently, the romtag must be in a list in ExecBase,
or in special areas of ram to be autodetected, but the romtag IDs are
obliterated just in case of future OS change where other areas may
be autodetected. In any situation that exit() is to be called, we are
going to return to the OS, and not softload, so the IDs are overwritten
to be safe. */
void exit2(ULONG error)
{
KillRomTags();
exit(error);
}
/* MyExit returns RAM allocated for the ROM before exiting */
void MyExit(error,TempROM)
ULONG error, *TempROM;
{
if((ULONG)TempROM==FASTROMLOC)
{
FreeMem((ULONG *)FASTROMLOC,ROMSIZE);
}
else
{
if(TempROM) WallFreeMem(TempROM,ROMSIZE);
}
exit2(error);
}
/* TableFill13 build 68040 MMU tables for a 1.3 Bonus kickstart image.
This improved version writes the 040 MMU tables into the temporary
ram covered by the 1.3 rom image, rather than at the final address (unless
they coinside). This allows me to delay Disable()ing the system until
much later, and to not corrupt any possible previous rom or data at
7f80000-7ffffff until I am very close to rebooting. */
void TableFill13(TempROM, cache)
ULONG *TempROM, cache;
{
ULONG *TempTable, PageField;
int i;
/*
The 1.3 bonus is very sneaky. It is setup with built-in 030 MMU tables,
and code to add the motherboard fast ram, read the real time clock and
to start the hard drives. The 1.3 ROM and Bonus is more than 256K but
less than 512K. There is plenty of room to add 68040 MMU tables as well.
The area from 7f80000 to 7fbffff is standard 256K 1.3 kickstart. MMU tables
map, or mirror that to f80000 to fbffff and to fc0000 to ffffff, to make
it look like a standard ROM system. The area in 7fc0000 to 7ffffff is
mapped to f00000 to f7ffff. 1.3 Kickstart will read this area for any
romtags; they do not have to be linked into any system list as with other
locations. In the mirror is a romtag which initializes the clock, ram, and
hard drive. In the assembly module, I built my own romtag, which
SetFunction()s ColdCapture(). 2.0 and later exec honors the 1.3 execbase
structure and will run the 1.3 execbase ColdCapture() vector before it
realizes that it is not a 2.0+ execbase and relocates it. My Romtag
then reloads the MMU and jumps back into 1.3, providing hardware
(Keyboard) reboot recovery. Obviously anything which overwrites
ColdCapture() without chaining it will cause the hardware reboot
recovery process to fail. As a result, I blast my vector in (I do not
chain) each time the romtag is run.
*/
/* Calculate Pointer to 1st level MMU table in temporary RAM */
TempTable = (ULONG *)(0x46000L + (ULONG)TempROM);
/*Fill 1st level table */
for (i = 1; i < 128; i++) *(TempTable+i) = 0L;
/* Point entry for lowest 32 Meg block to 2nd level table */
*TempTable = ((0x7fc8000L & L1MASK) | UDTRESIDENT); /* Point to Level 2 Table */
/* Calculate 2nd Level table location in temporary ROM space */
TempTable = (ULONG *)(0x48000L + (ULONG)TempROM);
/* Fill in 2nd level table with pointers to 3rd level table */
for (i=64; i<128; i++) *(TempTable+i)=0L;
for (i=0; i<64; i++)
*(TempTable+i)=(((0x7fca000L+i*128) & L2MASK) | UDTRESIDENT);
/* Calculate 3rd level table address */
TempTable = (ULONG *)(0x4a000L + (ULONG)TempROM);
/* Fill in 3rd level table for lowest 15 Meg */
PageField = CM_GLOBAL | CM_INH_SER | PDTRESIDENT;
for (i=0; i<1984; i++) /*Romaddr/pagesize = 0xf80000/0x2000 = 1984 pages*/
*(TempTable+i) = (((8192L*i) & L3MASK) | PageField);
/* Turn on Z2 caching, if asked for */
if(cache>0)
{
PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;
for(i=256; i<1280; i++) *(TempTable+i)=(((8192L*i) & L3MASK) | PageField);
}
/* Do ROM area, make write protected */
PageField = CM_GLOBAL | CM_COPYBACK | WR_PROTECT | PDTRESIDENT;
for (i=0; i<64; i++) /* Romsize/pagesize = 512K/8K = 64 pages */
*(TempTable+i+1984)=(((FASTROMLOC+(8192L*i)) & L3MASK) | PageField);
/* Fold over 7fc0000-7ffffff into F00000-F7ffff so romtags can be found */
PageField = CM_GLOBAL | CM_COPYBACK | WR_PROTECT | PDTRESIDENT;
for (i=0; i<32; i++)
*(TempTable+i+2016)=(((FASTROMLOC+(8192L*i)) & L3MASK) | PageField);
/* Make the area from f80000 to fc0000 mirror at fc0000 - ffffff */
PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;
for (i=0;i<32;i++)
*(TempTable+i+1920)=(((0x7fc0000L+(8192L*i)) & L3MASK) | PageField);
}
/* TableFill is the general purpose MMU table fill algorithm and requires
considerably more information. The Pointers to the MMU tables must
point to properly allocated and aligned memory space. */
void
TableFill(MMUTable, MMUTable2, MMUTable3, Z3MMUTable2, Z3MMUTable3, ROMADDR,
cache2, cache3, MyConfigStruct, numblocks)
ULONG *MMUTable, *MMUTable2, *MMUTable3, *Z3MMUTable2, *Z3MMUTable3,
ROMADDR, cache2, cache3, numblocks;
struct ConfigureIt *MyConfigStruct;
{
ULONG PageField;
int i,j;
/* The MMU address translation tree has been optimized into three memory
areas for memory defragmentation purposes. The upper level is 128
32 bit pointers. These must be adjacent, by definition. However,
the second and third level tables do not. Once allocated on a suitable
boundary, all 2nd and 3rd level tables are adjacent in two blocks of
RAM. The same technique is used later for Zorro III MMU tables */
/* Each element of MMUTable[n] points to a 2nd level table representing
32 Megabytes. We only care about the lowest 16 Meg, so zero out
all but the first entry */
for (i = 1; i < 128; i++) *(MMUTable+i) = 0L;
*MMUTable = (((ULONG)MMUTable2 & L1MASK) | UDTRESIDENT); /* Point to Level 2 Table */
/* 2nd Level Table initialization for lowest 32 Meg. There are
128 entries in the 2nd level table, each pointing to a
third level table which, in this MMU setup, contains the
translated addresses for each block of memory. */
/* Zero out pointers to 3rd level tables for upper 16 Meg block */
for (i=64; i<128; i++) *(MMUTable2+i)=0L;
/*Set 2nd Level pointers to 3rd level tables covering lowest 16 Meg. */
for (i=0; i<64; i++)
*(MMUTable2+i)=(((ULONG)&MMUTable3[i*32] & L2MASK) | UDTRESIDENT);
/* Set up 3rd level Tables for lowest 16 Meg. Each third
Level table represents 256K. */
/* Since, in this implementation, all third level tables reside adjacent
to one another, a total of 2048 8K (2K*8K = 16M) entries exist. The
following 'for' loops takes advantage of this fact for table
initialization purposes */
/* Do from 0 to just prior to ROM (All non-cacheable)*/
PageField = CM_GLOBAL | CM_INH_SER | PDTRESIDENT;
for (i=0; i<1984; i++) /*Romaddr/pagesize = 0xf80000/0x2000 = 1984 pages*/
*(MMUTable3+i) = (((8192L*i) & L3MASK) | PageField);
/* Do ROM area, make write protected */
PageField = CM_GLOBAL | CM_COPYBACK | WR_PROTECT | PDTRESIDENT;
for (i=0; i<64; i++) /* Romsize/pagesize = 512K/8K = 64 pages */
*(MMUTable3+i+1984)=(((ROMADDR+(8192L*i)) & L3MASK) | PageField);
/* Turn on Z2 caching, if asked for */
if(cache2>0)
{
PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;
for(i=256; i<1280; i++) *(MMUTable3+i)=(((8192L*i) & L3MASK) | PageField);
}
/* ZorroIII initialization */
if(MyConfigStruct->StartAddr>=Z3STARTADDR)
{
/* Level 1 Table Generation for Zorro III area; Tables are
built regardless of the Transparent Translation Registers */
/* Assumption: MyConfigStruct->StartAddr is on a 32Meg Boundary
(FindZorro3Start() ensures this). Any Board less
than 32 Meg will generate a 32 MB MMU table for Zorro
III areas */
for(i=0;i<numblocks;i++)
*(MMUTable+(MyConfigStruct->StartAddr/0x02000000L)+i)=
((((ULONG)Z3MMUTable2+i*0x200L) & L1MASK) | UDTRESIDENT);
/* Level 2 Tables for Zorro III space */
for (i=0L;i<(128L*numblocks);i++)
{
*(Z3MMUTable2+i)=
(((ULONG)&Z3MMUTable3[i*32] & L2MASK) | UDTRESIDENT);
/* Level 3 Tables for Zorro III space */
PageField = CM_GLOBAL | CM_COPYBACK | PDTRESIDENT;
if(!cache3) PageField = CM_GLOBAL | CM_INH_SER | PDTRESIDENT;
for (j=0L; j<32L; j++)
*(Z3MMUTable3+i*32L+j) =
(((8192L*(32L*i+j)+MyConfigStruct->StartAddr) & L3MASK) | PageField);
}
}
}
/* FindZorro3Start() determines whether or not a Bridgeboard exists and
and determines upper and lower bounds for MMU tables to cover
the Zorro III ram and I/O cards. The start address is rounded down to
the next lowest 32 MB boundary if it is not on one. The end address is
rounded up to the next higher 32 MB boundary if not on one. The MMU
tables must be filled in a 32 MB increment, so this is a valid choice */
ULONG FindZorro3Start(struct ConfigureIt *MyConfigStruct)
{
ULONG temp;
struct ConfigDev *myCD=NULL;
struct Library *ExpansionBase = NULL;
struct MemHeader *mem;
MyConfigStruct->StartAddr = Z3ENDADDR;
MyConfigStruct->EndAddr = 0L;
MyConfigStruct->BridgeBoard = 0L;
if((ExpansionBase=OpenLibrary("expansion.library",0L))==NULL)
{
MyConfigStruct->StartAddr = 0L;
return(0L);
}
/* Loop though autoconfigured boards */
while(myCD=FindConfigDev(myCD,-1L,-1L))
{
/* Check and mark if Bridgeboard is found */
if(myCD->cd_Rom.er_Manufacturer==0x201 && myCD->cd_Rom.er_Product==1)
MyConfigStruct->BridgeBoard=1L;
/* Check for a Zorro III board (any type). Z3STARTADDR = 0x10000000 */
if ((ULONG)(myCD->cd_BoardAddr) >= Z3STARTADDR)
{
/* Check for board less than Z3 end address; In case the OS
does not store the config items in increasing order,
or in a random order */
if ((ULONG)(myCD->cd_BoardAddr) < MyConfigStruct->StartAddr)
MyConfigStruct->StartAddr = (ULONG)(myCD->cd_BoardAddr);
/* I am assuming that when you take a previous board address and
add its length, you will get the address of the next board,
therefore, I test with >= rather than > in the following statement: */
if ((ULONG)(myCD->cd_BoardAddr) >= MyConfigStruct->EndAddr)
{
/* I am not sure how Slot Size and Board Size relate. I have seen
a Progressive Zorro III ram card which only had 16 of 64 Meg
populated. In that case 64K * SlotSize and BoardSize did not
agree. To be conservative, I will take the larger range of the
two. This ensures that the area will be covered, although it might
be a bit much. */
if(65536L*(ULONG)myCD->cd_SlotSize > (ULONG)myCD->cd_BoardSize)
{
MyConfigStruct->EndAddr =
(ULONG)(myCD->cd_BoardAddr) +
65536L*(ULONG)(myCD->cd_SlotSize);
}
else /* BoardSize > than 64K * SlotSize */
{
MyConfigStruct->EndAddr =
(ULONG)(myCD->cd_BoardAddr) +
(ULONG)(myCD->cd_BoardSize);
}
}
}
}
/* This code double checks the memory lists against my board config sizing
logic above. Should a ZorroIII memory board not correctly work due to the
above logic, it should be found via the memory lists and corrected.
Zorro III space is defined as anywhere between 0x10000000 and 0xffffffff */
/* Prevent anyone from walking the memory lists while we are using them */
Forbid();
/* Get pointer to system memory lists */
mem=(struct MemHeader *)(SysBase->MemList.lh_Head);
/* Loop until all nodes have been checked */
while (mem->mh_Node.ln_Succ)
{
/* Check lower bounds of memory area against the beginning of Zorro III
space and the lowest Zorro III address detected */
if((ULONG)mem->mh_Lower >= Z3STARTADDR)
{
if( (ULONG)mem->mh_Lower < MyConfigStruct->StartAddr)
{
MyConfigStruct->StartAddr = (ULONG)(mem->mh_Lower);
}
/* Check upper memory list bounds against the largest Z3 board found */
if((ULONG)mem->mh_Upper > MyConfigStruct->EndAddr)
{
MyConfigStruct->EndAddr = (ULONG)(mem->mh_Upper);
}
}
/* Go to next node in memory list */
mem=(struct MemHeader *)(mem->mh_Node.ln_Succ);
}
/* We are done, so let system continue */
Permit();
/* If StartAddr was never modified, then there is no Zorro III ram or I/O
in this system and set it to a value other routines will detect */
if(MyConfigStruct->StartAddr == Z3ENDADDR) MyConfigStruct->StartAddr=0L;
CloseLibrary(ExpansionBase);
/* Now round start and end address to nearest full 32 MB increment */
if(MyConfigStruct->StartAddr >= Z3STARTADDR)
{
/* The following code will round StartAddr to the next lowest 32MB boundary
if it is not already on one. */
MyConfigStruct->StartAddr = MyConfigStruct->StartAddr/0x02000000L;
MyConfigStruct->StartAddr *= 0x02000000L;
/* We want to round the end address up to the next higher 32 MB boundary
if it does not end on a 32 MB boundary. */
temp = MyConfigStruct->EndAddr/0x02000000L;
temp *= 0x02000000L;
if (temp != MyConfigStruct->EndAddr) MyConfigStruct->EndAddr = temp + 0x02000000L;
}
return (0L);
}
/* This replaces the Lattice "stricmp()" function, plus it's a better form
for my needs here. */
static BOOL striequ(s1,s2)
char *s1,*s2;
{
BOOL aok;
while (*s1 && *s2 && (aok = (*s1++ & 0xdf) == (*s2++ & 0xdf)));
return (BOOL) (!*s1 && aok);
}
/* Page tables and other MMU stuff must be on a page sized boundary, and
that boundary must be a power of two. This routine allocates such an
aligned block of memory. */
/* AllocAligned now allocates a 32 byte wall around the the Allocation to
help protect against memlist tail overwrites and other programs which
overrun their adjacent memory allocations. The address returned is the
'safe' aligned address. 32 bytes before and 32+size bytes past the
'safe' address are allocated. */
void *AllocAligned(size,bound)
ULONG size;
ULONG bound;
{
void *mem, *aligned;
ULONG length;
length=size+bound+WALLSIZE;
if (!(mem = (void *)AllocMem(length,MEMF_FAST))) return NULL;
Forbid();
aligned = (void *)((((ULONG)mem + bound - 1) & ~(bound - 1))-WALL);
FreeMem(mem,length);
mem = (void *)AllocAbs(size+WALLSIZE,aligned);
Permit();
mem=(void *)((ULONG)mem+WALL);
return mem;
}
void PatchRom(RomAddr)
ULONG *RomAddr;
{
ULONG i,DStart, *LTemp;
UWORD Test,*Start;
LTemp=(ULONG *)(LogRomStart+4);
DStart=(*(LTemp)-LogRomStart)+(ULONG)RomAddr;
Start=(UWORD *)DStart;
/* Patch # 1 - Remove Rom Checksum error branch */
for(i=0;i<5000;i++) /* 5000 word limit from Start address for search */
{
if((Test=*(Start+i))==0x4685)
if((Test=*(Start+i+1))==0x6600)
{
*(Start+i)=0x7A00; /* Patch out Rom checksum test */
break; /* Not d5 -> moveq #0,d5 following branch test then*/
} /* Error check Always passes! */
}
/* Patch # 2 - Prevent 040 mTTx registers from being blown away
by patching in NOPS over offending opcodes */
for(i=0;i<25000;i++) /*Search up to 25K words away from start for patch */
{
if(*(Start+i)==MOVEC)
{
/* Test for 0x4E7B0003 thru 0x4E7B0007 and 0x4E7B0805 thru 0x4E7B0807
and change to 0x4E714E71 (Dual NOPs) */
Test = *(Start+i+1) & 0xFFF;
if(Test > 2 && Test < 8 || Test > 804 && Test < 808)
{
*(Start+i) = NOP;
*(Start+i+1) = NOP;
}
}
}
}
int main(argc,argv)
int argc;
char *argv[];
{
ULONG i, cpu, myTC, myTC30, file, cache, FastRom, numblocks;
ULONG *MMUTable2,*MMUTable3, *ROM32, *MMUTable, *Z3MMUTable2, *Z3MMUTable3;
ULONG Z3L2size, Z3L3size, *MMU030Table, both, Z3All, rm13, *TempROM;
ULONG count, MMUOverride, enttx;
struct ConfigureIt MyConfigStruct;
/* If they're just asking for help */
if (argc >= 2 && argv[1][0] == '?') {
printf("\n\2337mSoftBoot %s\2330m [NOCACHEZ2][KILLROM][NOCATCHROM][ONETHREE]\n",
PROGRAM_VERSION);
printf(" [BOTH][SOFTBOOT][NOBUSERRORS][FASTROM]\n");
printf(" [ENTTX][OVRMMU][NOCACHEZ3][Z3ALL]\n");
exit2(0L);
}
enttx=0L; /* Flag for command line parsing for enttx option */
rm13=0L; /* Not loading 1.3 Rom by default */
both=0L; /* Not building both 030 and 040 MMU tables by default */
cache=1L; /* Turn on Zorro II caching by default */
Z3cache=1L; /* Turn on Zorro III caching by default */
BusErr=0L; /* Do not turn off the bus error HW by default */
FastRom=0L; /* Not performing just a fastrom */
CatchRom=0L; /* Do not patch the exception handler for invalid access */
MMUTable=NULL; /* Set Pointer to NULL */
MMU030Table=NULL; /* Set Pointer to NULL */
LogRomStart=BASEROMLOC; /* Logical ROM start address */
ROM32 = (ULONG *)FASTROMLOC; /* Physical (relocated) Rom Address */
MMUOverride=0L; /* Flag to override existing MMU setup */
Z3All = 0L; /* Do not make 040 MMU tables for all of Z3 space */
/* Search for Zorro III start address and length */
(void)FindZorro3Start((struct ConfigureIt *)&MyConfigStruct);
/* Find if there is a bridgeboard and turn off Z2 cache if so */
if (MyConfigStruct.BridgeBoard) cache=0L;
cpu=GetCPUType();
/* Parse Command line */
if (argc>1)
{
for(i=1;i<argc;i++)
{
if ((int)striequ(argv[i],"NOCACHEZ2")) cache=0L;
if ((int)striequ(argv[i],"NOCACHEZ3")) Z3cache=0L;
if ((int)striequ(argv[i],"ONETHREE")) {both=1L; rm13=1L;
LogRomStart=0x00fc0000L;}
if ((int)striequ(argv[i],"BOTH")) both=1L;
if ((int)striequ(argv[i],"KILLROM")) {KillRomTags();
MyColdReboot();}
if ((int)striequ(argv[i],"NOBUSERRORS")) BusErr=1L;
if ((int)striequ(argv[i],"FASTROM")) FastRom=1L;
if ((int)striequ(argv[i],"NOCATCHROM")) CatchRom=1L;
if ((int)striequ(argv[i],"SOFTBOOT")) {KillRomTags();
ColdReboot();}
if ((int)striequ(argv[i],"ENTTX")) if(cpu==68040L) enttx = 1L;
if ((int)striequ(argv[i],"OVRMMU")) MMUOverride=1L;
if ((int)striequ(argv[i],"Z3ALL")) Z3All=1L;
}
}
if(enttx>0L) {ForceTTX(); exit2(0);}
/* Let's Test as much as we can, before we get in too far to back out */
printf("%ld CPU found.\n",cpu);
if (cpu !=68020L && cpu != 68030L && cpu !=68040L)
{
printf("SoftBoot Requires a 68030 or 68040 CPU!\n");
exit2(20L);
}
if(cpu==68020L) cpu=68030L; /* I'm assuming an '851 */
myTC=0L;
myTC30=0L;
if(cpu==68040L) myTC=GetTC040();
if(cpu==68030L) myTC30=GetTC030();
if (!MMUOverride && ((cpu == 68040L && myTC) ||
(cpu == 68030L && (myTC30 & TCMASK030))))
{
printf("FastRom MMU already in operation!\n");
exit2(0L);
}
if(cache) printf("Zorro II area will be cached!\n");
if (FastRom)
{
both=0L; /* Override Both parameter if Fastrom is called for */
ROM32 = (ULONG *)AllocAligned(ROMSIZE,ROUND030);
if(!ROM32)
{
printf("FASTROM Memory Allocation Failure! Reboot to defragment!\n");
exit2(20L);
}
TempROM=ROM32;
}
else /* We're softbooting a new OS */
{
TempROM=AllocAbs(ROMSIZE,(APTR)FASTROMLOC);
if(!TempROM)
{
TempROM=AllocAligned(ROMSIZE,0x1000L);
/* Check for No memory or overlap with final destination */
if (!TempROM || (((ULONG)TempROM+ROMSIZE+WALL >= FASTROMLOC) &&
((ULONG)TempROM & FASTROMADDRMASK)))
{
printf("TempROM Memory Allocation Failure. Reboot to defragment memory!\n");
exit2(20L);
}
}
/* The final ROM destination is FASTROMLOC (0x7f80000). At a later point, I
will Disable() so I can stomp on this area without crashing someone else.
So I copy the disk file to 0x7f80000 or a temporary buffer now if 0x7f80000
was not directly available, so the read() will not break the Disable() and
allow the system to crash and burn by having another task use memory
I just overwrote. */
if(!rm13)
{
file=open("devs:Kickstart",0L);
if(file==-1L)
{
printf("Error opening devs:Kickstart!\n");
close(file);
MyExit(20L,TempROM);
}
count=read(file, TempROM, ROMSIZE);
if(count != ROMSIZE)
{
printf("Devs:Kickstart wrong length!\n");
close(file);
MyExit(20L,TempROM);
}
}
else
{
file=open("devs:Kickstart1.3",0L);
if(file==-1L)
{
printf("Error opening devs:Kickstart1.3!\n");
close(file);
MyExit(20L,TempROM);
}
count=read(file, TempROM, BONUSSIZE1_3);
if(count != BONUSSIZE1_3)
{
printf("Devs:Kickstart1.3 wrong length!\n");
close(file);
MyExit(20L,TempROM);
}
}
}
/* No need to turn caches off if fastromming */
if(!FastRom)CachesOff();
if ((cpu==68030L || both) && !rm13)
{
MMU030Table = (ULONG *)AllocAligned(MMU030TABLESIZE,ROUND030);
if (!MMU030Table || !FastRom && ((ULONG)MMU030Table > Z3STARTADDR))
{
if(FastRom)
{
printf("Out of Memory For MMU tables! Reboot and Retry\n");
}
else
{
printf("No Memory on A3000|A4000 Motherboard for MMU tables! Reboot to defragment.\n");
}
MyExit(20L,TempROM);
}
}
if(cpu==68040L || both)
{
numblocks=0L;
if(!rm13 && MyConfigStruct.StartAddr>=Z3STARTADDR)
{
printf("Zorro III enabled via MMU at 0x%08lx\n",MyConfigStruct.StartAddr);
/* Count Number of 32 Meg Blocks needed for Zorro III devices */
if (MyConfigStruct.StartAddr >= Z3STARTADDR ) /* if there was Z3 Ram... */
{
/* Estimate number of 32 Megabyte RAM areas */
numblocks = (MyConfigStruct.EndAddr - MyConfigStruct.StartAddr)/0x2000000L;
/* Z3ALL flag forces all Zorro III ram to be mapped. This case is
required if CBM moves start of Zorro III RAM or separates I/O
space from ram space for 040 mTTx registers. In such a case, the
old operating system's idea of Zorro III space would not match
the new operating system, and faulty MMU tables would be built.
The Z3ALL flag builds MMU tables at great expense in ram, but
allows the new OS to work until a new softboot is made available.
So, to make the Z3 routines map all of Z3 space, we set
MyConfig.StartAddr to the beginning of Z3 space and set
numblocks to cover the entire range. */
if(Z3All > 0L)
{
numblocks=(Z3ENDADDR - Z3STARTADDR + 1L)/0x02000000L;
MyConfigStruct.StartAddr=Z3STARTADDR;
}
}
}
Z3L3size=numblocks*Z3L3SIZEPERBLOCK; /*Third level tables' size */
Z3L2size=numblocks*Z3L2SIZEPERBLOCK; /*Second Level Tables' size */
NumMemAreas=3L; /* Number of areas to protect via Kickmemlist */
/* Get the memory for the basic 68040 MMU tables. */
if(!rm13)
{
MMUTable = (ULONG *)AllocAligned(TABSIZE,ROUND);
MMUTable2 = (ULONG *)AllocAligned(TABSIZE,ROUND);
MMUTable3 = (ULONG *)AllocAligned(LEV3TABSIZE,ROUND);
Z3MMUTable2 = NULL;
Z3MMUTable3 = NULL;
/* Allocate Zorro III 2nd and third level tables */
if(MyConfigStruct.StartAddr>=Z3STARTADDR)
{
Z3MMUTable2 = (ULONG *)AllocAligned(Z3L2size,ROUND);
Z3MMUTable3 = (ULONG *)AllocAligned(Z3L3size,ROUND);
/* Update KickMemList Tables for protection of Zorro III tables
Note areas are protected via one WALL before and after actual
Area used. */
if(!FastRom)
{
MemListArray[6] = (ULONG)Z3MMUTable2-WALL;
MemListArray[7] = Z3L2size+WALLSIZE;
MemListArray[8] = (ULONG)Z3MMUTable3-WALL;
MemListArray[9] = Z3L3size+WALLSIZE;
NumMemAreas=5L; /* Now five memory areas to protect */
}
}
/*
Last safety check that all MMU tables were allocated. If not,
return memory that was allocated and exit the program.
For stability, when booting a new OS, the MMU tables must be
in A3000|A4000 motherboard range, which are constant and
available through reset. For FastRom, any RAM is OK.
*/
if (!MMUTable || !MMUTable2 || !MMUTable3 ||
!FastRom && ((ULONG)MMUTable > Z3STARTADDR) ||
!FastRom && ((ULONG)MMUTable2 > Z3STARTADDR) ||
!FastRom && ((ULONG)MMUTable3 > Z3STARTADDR) ||
!FastRom && ((ULONG)Z3MMUTable2 > Z3STARTADDR) ||
!FastRom && ((ULONG)Z3MMUTable3 > Z3STARTADDR) ||
((MyConfigStruct.StartAddr>=Z3STARTADDR) && (!Z3MMUTable3 || !Z3MMUTable2)))
{
if (both && MMU030Table) WallFreeMem(MMU030Table,MMU030TABLESIZE);
if (MMUTable) WallFreeMem(MMUTable,TABSIZE);
if (MMUTable2) WallFreeMem(MMUTable2,TABSIZE);
if (MMUTable3) WallFreeMem(MMUTable3,LEV3TABSIZE);
if (Z3MMUTable2) WallFreeMem(Z3MMUTable2,Z3L2size);
if (Z3MMUTable3) WallFreeMem(Z3MMUTable3,Z3L3size);
printf("No Memory on A3000|A4000 Motherboard for MMU tables! Reboot to defragment.\n");
MyExit(20L,TempROM);
}
/* Setup KickMemList via MemListArray - Note Safety wall is included! */
if(!FastRom)
{
MemListArray[0] = (ULONG)MMUTable-WALL;
MemListArray[1] = TABSIZE+WALLSIZE;
MemListArray[2] = (ULONG)MMUTable2-WALL;
MemListArray[3] = TABSIZE+WALLSIZE;
MemListArray[4] = (ULONG)MMUTable3-WALL;
MemListArray[5] = LEV3TABSIZE+WALLSIZE;
/* Now fill the MMU tables that we have successfully allocated -
The final location of the new ROM will always be FASTROMLOC */
TableFill(MMUTable, MMUTable2, MMUTable3, Z3MMUTable2, Z3MMUTable3,
FASTROMLOC, cache, Z3cache,
(struct ConfigureIt *)&MyConfigStruct, numblocks);
}
else /* Fill MMU tables for FastRom */
{
TableFill(MMUTable, MMUTable2, MMUTable3, Z3MMUTable2, Z3MMUTable3,
(ULONG)TempROM, cache, Z3cache,
(struct ConfigureIt *)&MyConfigStruct, numblocks);
}
}
else /* rm13 */
{
/* Perform 1.3 MMU magic */
TableFill13(TempROM, cache);
MMUTable=(ULONG *)0x7fc6000L;
}
SRP = (ULONG)MMUTable;
}
if (cpu==68030L || both)
{
/* Fill 030 MMU tables */
if(!rm13) /* Note 1.3 bonus builds KS1.3 030 MMU tables */
{
for (i=0;i<32;i++) MMU030Table[i]=((PAGESIZE030 * i) + 0x41L);
for (i=32;i<8160;i++) MMU030Table[i]=((PAGESIZE030 * i) + 1L);
for (i=8160;i<8192;i++) MMU030Table[i]=((PAGESIZE030 * i) + 0x41L);
if (cache) for (i=4;i<21;i++) MMU030Table[i]=((PAGESIZE030 * i) + 1L);
MMU030Table[31] = (ULONG)ROM32 | 5L;
if(!FastRom) /*update kickmemList if we are booting a new OS */
{
if (both) /* 040 MMU tables are already loaded into the kickmemlist*/
{
MemListArray[NumMemAreas*2] = (ULONG)MMU030Table-WALL;
MemListArray[NumMemAreas*2+1]= MMU030TABLESIZE+WALLSIZE;
NumMemAreas++;
}
else /* Only the 030 table needs to be protected */
{
MemListArray[0]= (ULONG)MMU030Table-WALL;
MemListArray[1]= MMU030TABLESIZE+WALLSIZE;
NumMemAreas=1L;
}
}
}
}
/* 030 MMU Register values */
TC030 =0x80f0d400L;
CRP0 =0x7fff0002L;
CRP1 =(ULONG)(MMU030Table)&~0xfL;
PhyRomStart= (ULONG)ROM32; /* Wrote into romtag, for its use */
/* Now I have to set up the MMU. The Supervisor Root Pointer tells the MMU about
the table I've set up, and the Translation Control register will turn
the thing on. */
if(!FastRom)
{
/* Softloading a new OS */
if(rm13)
{
Disable();
SF_Supervisor();
CachesOff();
if((ULONG)TempROM != FASTROMLOC)
for(i=0;i<0x20000;i++) *((ULONG *)FASTROMLOC+i) = *(TempROM+i);
MakeRomTag13();
CachesOff();
if(cpu!=68040L)
{
JTRom13030();
}
else
{
JTRom();
}
}
else /* 2.0 or later */
{
PatchRom(TempROM);
Disable();
SF_Supervisor();
MakeRomTag();
if((ULONG)TempROM!=FASTROMLOC)
for(i=0;i<0x20000;i++) *((ULONG *)FASTROMLOC+i) = *(TempROM+i);
CachesOff();
JTRom();
}
}
else /* Fastrom Operation */
{
KillRomTags(); /* Blow away rontag headers so they can't ever be found */
CopyMemQuick((ULONG *)BASEROMLOC,ROM32,ROMSIZE);
CachesOff();
SpeedRom();
}
exit(0L);
}